/*
 * Copyright (C) 2009 M. Hautle.
 * 
 * This file is part of TrackedBean.
 * 
 * TrackedBean is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free
 * Software Foundation, either version 3 of the License, or (at your option) any later version.
 * 
 * TrackedBean is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public License along with TrackedBean. If not, see <http://www.gnu.org/licenses/>.
 */
package ch.trackedbean.business;

import ch.trackedbean.common.*;

/**
 * This is an abstract base class for business components - it provides an indirect access to model properties throug a {@link IPropertyResolver}.<br>
 * Use this class for components which may be used on different data structures (i.e. if you need to perform the same logic on a domain object and a
 * corresponding DTO). Use {@link #get(String, Object, Object)} (or a conveniance version of it) to retrive the value of a property.<br>
 * You should use the property names of the domain object as property key if you plan to use the {@link MappingResolver} to reuse the component for mapped
 * beans.<br>
 * 
 * @author M. Hautle
 */
public abstract class AbstractBusinessComponent {
	/** The resolver to use. */
	protected IPropertyResolver resolver;

	/**
	 * Returns the current resolver.
	 * 
	 * @return The resolver.
	 */
	public IPropertyResolver getResolver() {
		return resolver;
	}

	/**
	 * Sets the resolver to use.
	 * 
	 * @param resolver The resolver
	 */
	public void setResolver(IPropertyResolver resolver) {
		this.resolver = resolver;
	}

	/**
	 * Resolves the given property key to the representing property name/EL expression.
	 * 
	 * @param key The property key
	 * @param type The type for which to fetch the information
	 * @return The corresponding property/EL expression
	 * @throws TechnicalException If something went wrong
	 */
	public String getExpression(String key, Class type) throws TechnicalException {
		return resolver.getPath(key, type);
	}

	/**
	 * Fetches the value of the given bean denoted by the given property key.
	 * 
	 * @param <S> The type
	 * @param key The property key
	 * @param bean The bean from which to fetch the value
	 * @param fallback The fallback value
	 * @return The fetched value or the fallback
	 */
	protected <S> S get(String key, Object bean, S fallback) {
		return resolver.get(key, bean, fallback);
	}

	/**
	 * Conveniance method for {@link #get(String, Object, Object)}.
	 * 
	 * @param <S> The type
	 * @param key The property key
	 * @param type The desired return type
	 * @param bean The bean from which to fetch the value
	 * @param fallback The fallback value
	 * @return The fetched value or the fallback
	 */
	protected <S> S get(String key, Class<S> type, Object bean, S fallback) {
		return resolver.get(key, bean, fallback);
	}

	/**
	 * Conveniance method for {@link #get(String, Object, Object)}.
	 * 
	 * @param key The property key
	 * @param bean The bean from which to fetch the value
	 * @param fallback The fallback value
	 * @return The fetched value or the fallback
	 */
	protected String getString(String key, Object bean, String fallback) {
		return get(key, bean, fallback);
	}

	/**
	 * Conveniance method for {@link #get(String, Object, Object)}.
	 * 
	 * @param key The property key
	 * @param bean The bean from which to fetch the value
	 * @param fallback The fallback value
	 * @return The fetched value or the fallback
	 */
	protected Number getNumber(String key, Object bean, Number fallback) {
		return get(key, bean, fallback);
	}

	/**
	 * Conveniance method for {@link #getNumber(String, Object, Number)}.
	 * 
	 * @param key The property key
	 * @param bean The bean from which to fetch the value
	 * @param fallback The fallback value
	 * @return The fetched value or the fallback
	 */
	protected byte getByte(String key, Object bean, byte fallback) {
		final Number res = getNumber(key, bean, null);
		return res != null ? res.byteValue() : fallback;
	}

	/**
	 * Conveniance method for {@link #getNumber(String, Object, Number)}.
	 * 
	 * @param key The property key
	 * @param bean The bean from which to fetch the value
	 * @param fallback The fallback value
	 * @return The fetched value or the fallback
	 */
	protected short getShort(String key, Object bean, short fallback) {
		final Number res = getNumber(key, bean, null);
		return res != null ? res.shortValue() : fallback;
	}

	/**
	 * Conveniance method for {@link #getNumber(String, Object, Number)}.
	 * 
	 * @param key The property key
	 * @param bean The bean from which to fetch the value
	 * @param fallback The fallback value
	 * @return The fetched value or the fallback
	 */
	protected int getInt(String key, Object bean, int fallback) {
		final Number res = getNumber(key, bean, null);
		return res != null ? res.intValue() : fallback;
	}

	/**
	 * Conveniance method for {@link #getNumber(String, Object, Number)}.
	 * 
	 * @param key The property key
	 * @param bean The bean from which to fetch the value
	 * @param fallback The fallback value
	 * @return The fetched value or the fallback
	 */
	protected long getLong(String key, Object bean, long fallback) {
		final Number res = getNumber(key, bean, null);
		return res != null ? res.longValue() : fallback;
	}

	/**
	 * Conveniance method for {@link #getNumber(String, Object, Number)}.
	 * 
	 * @param key The property key
	 * @param bean The bean from which to fetch the value
	 * @param fallback The fallback value
	 * @return The fetched value or the fallback
	 */
	protected float getFloat(String key, Object bean, float fallback) {
		final Number res = getNumber(key, bean, null);
		return res != null ? res.floatValue() : fallback;
	}

	/**
	 * Conveniance method for {@link #getNumber(String, Object, Number)}.
	 * 
	 * @param key The property key
	 * @param bean The bean from which to fetch the value
	 * @param fallback The fallback value
	 * @return The fetched value or the fallback
	 */
	protected double getDouble(String key, Object bean, double fallback) {
		final Number res = getNumber(key, bean, null);
		return res != null ? res.doubleValue() : fallback;
	}

	/**
	 * Conveniance method for {@link #get(String, Object, Object)}.
	 * 
	 * @param key The property key
	 * @param bean The bean from which to fetch the value
	 * @param fallback The fallback value
	 * @return The fetched value or the fallback
	 */
	protected char getChar(String key, Object bean, char fallback) {
		final Character c = get(key, bean, null);
		return c != null ? c.charValue() : fallback;
	}
}
